﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using TyNetCoreBlog.Helpers;
using TyNetCoreBlog.Models.Data;
using TyNetCoreBlog.Models.Entities;
using TyNetCoreBlog.Repository.RepositoryBase;

namespace TyNetCoreBlog.Repository
{
    public class BlogRepository : RepositoryBase<Blog, int>, IBlogRepository
    {
        public BlogRepository(AppDbContext dbContext):base(dbContext)
        {
        }

        /// <summary>
        /// 分页获取博客
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public Task<PagedList<Blog>> GetAllAsync(BlogResourceParameters parameters)
        {
            IQueryable<Blog> queryableBlogs = DbContext.Set<Blog>().Include(x => x.User)
                .Include(x => x.Category);
            if (!string.IsNullOrWhiteSpace(parameters.Keywords))
            {
                queryableBlogs = queryableBlogs.Where(x => x.Title.Contains(parameters.Keywords.ToLower()));
            }
            return PagedList<Blog>.CreateAsync(queryableBlogs, parameters.PageNum, parameters.PageSize);
            
            //var totalCount = queryableBlogs.Count();
            //var items = queryableBlogs.Skip((parameters.PageNum - 1) * parameters.PageSize)
            //    .Take(parameters.PageSize).ToList();
            //return Task.FromResult(new PagedList<Blog>(items, totalCount, parameters.PageNum, parameters.PageSize));

            
        }



        /// <summary>
        /// 重写GetAllAsync，按更新时间倒序
        /// </summary>
        /// <returns></returns>
        public override Task<IEnumerable<Blog>> GetAllAsync()
        {
            return Task.FromResult(DbContext.Set<Blog>()
                .OrderByDescending(x => x.UpdateTime).AsEnumerable());
        }


        /// <summary>
        /// 重写GetByConditionAsync，附加user、category信息
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public override Task<IEnumerable<Blog>> GetByConditionAsync(Expression<Func<Blog, bool>> expression)
        {
            return Task.FromResult(DbContext.Set<Blog>().Include(x => x.User).Include(x => x.Category)
                .Where(expression).AsEnumerable());
        }


        /// <summary>
        /// 通过tagid获取博客
        /// </summary>
        /// <param name="tagId"></param>
        /// <returns></returns>
        public Task<IEnumerable<Blog>> GetBlogByTagIdAsync(int tagId)
        {
            var blogs = from bs in DbContext.Set<Blog>().Include(x => x.User).Include(x => x.Category)
                        join bt in DbContext.Set<BlogTag>()
                        on bs.Id equals bt.BlogId
                        where bt.TagId == tagId
                        select bs;
            return Task.FromResult(blogs.AsEnumerable());
        }


        /// <summary>
        /// 重写GetByIdAsync，附加user、category信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public override Task<Blog> GetByIdAsync(int id)
        {
            return DbContext.Set<Blog>().Include(x => x.User).Include(x => x.Category)
                .Where(x => x.Id == id).FirstOrDefaultAsync();
        }


        /// <summary>
        /// 获取前几条博客
        /// </summary>
        /// <param name="topNum"></param>
        /// <returns></returns>
        public Task<IEnumerable<Blog>> GetTopBlogs(int topNum)
        {
            var blogs = DbContext.Set<Blog>().Include(x => x.User).Include(x => x.Category)
                .OrderByDescending(x => x.UpdateTime).Take(topNum).AsEnumerable();
            return Task.FromResult(blogs);
        }



        /// <summary>
        /// 获取热门文章
        /// </summary>
        /// <param name="topNum"></param>
        /// <returns></returns>
        public Task<IEnumerable<Blog>> GetHotBlogs(int topNum)
        {
            var blogs = DbContext.Set<Blog>().Include(x => x.User).Include(x => x.Category)
                .OrderByDescending(x => x.Views).Take(topNum).AsEnumerable();
            return Task.FromResult(blogs);
        }


        /// <summary>
        /// 获取博客所有年份
        /// </summary>
        /// <returns></returns>
        public async Task<List<int>> GetYearsAsync()
        {
            var years = await DbContext.Set<Blog>().GroupBy(x => x.CreateTime.Year, (key, value) => key).ToListAsync();
            years.Reverse();
            return years;
        }


        /// <summary>
        /// 博客按年分组归档
        /// </summary>
        /// <param name="years"></param>
        /// <returns></returns>
        public async Task<Dictionary<int, IEnumerable<Blog>>> BlogArchiveAsync(List<int> years)
        {
            var dic = new Dictionary<int, IEnumerable<Blog>>();
            foreach (var year in years)
            {
                var blogs = await DbContext.Set<Blog>().Include(x => x.User).Include(x => x.Category)
                    .AsNoTracking().Where(a => a.CreateTime.Year == year)
                    .OrderByDescending(a => a.CreateTime).ToListAsync();
                dic.Add(year, blogs);
            }
            return dic;
        }
    }
}
